package org.yang.parser;

import com.sun.istack.internal.NotNull;
import com.sun.istack.internal.Nullable;
import org.yang.parser.ast.*;
import org.yang.parser.types.Type;

import java.util.LinkedHashSet;
import java.util.Set;

public class Binding implements Comparable<Object> {

    public enum Kind{
        ATTRIBUTE,      // attr accessed with "." on some other object
        CLASS,          // class definition
        CONSTRUCTOR,    // __init__ functions in classes
        FUNCTION,       // plain function
        METHOD,         // static or instance method
        MODULE,         // file
        PARAMETER,      // function param
        SCOPE,          // top-level variable ("Scope" means we assume it can have attrs)
        VARIABLE        // local variable
    }

    private boolean isStatic = false;   // static fields/methods
    private boolean isSynthetic = false;// auto-generated bindings;
    private boolean isBuiltin = false;  // not from a source file

    @NotNull
    public String name;     // unqualified name
    @NotNull
    public Node node;
    @NotNull
    public String qname;    // qualified name
    public Type type;       // inferred type
    public Kind kind;       // name usage context

    public Set<Node> refs = new LinkedHashSet<>(1);

    // fields from Def
    public int start = -1;
    public int end = -1;
    public int line = -1;
    public int col = -1;
    public int bodyStart = -1;
    public int bodyEnd = -1;

    @Nullable
    public String fileOrUrl;

    public Binding(@NotNull String id, @NotNull Node node, @NotNull Type type, @NotNull Kind kind){
        this.name = id;
        this.qname = type.table.path;
        this.type = type;
        this.kind = kind;
        this.node = node;

        if(node instanceof Url){
            String url = ((Url) node).url;
            if(url.startsWith("file://")){
                fileOrUrl = url.substring("file://".length());
            } else {
                fileOrUrl = url;
            }
        } else {
            fileOrUrl = node.file;
            if(node instanceof Name){
                name = ((Name) node).id;
            }
        }
        initLocationInfo(node);
        Analyzer.self.registerBinding(this);
    }

    private void initLocationInfo(Node node){
        start = node.start;
        end = node.end;
        line = node.line;
        col = node.col;

        Node parent = node.parent;
        if((parent instanceof FunctionDef && ((FunctionDef) parent).name == node )
                || (parent instanceof ClassDef && ((ClassDef) parent).name == node)){
            bodyStart = parent.start;
            bodyEnd = parent.end;
        } else if(node instanceof Module){
            name = ((Module) node).name;
            start = 0;
            end = 0;
            bodyStart = node.start;
            bodyEnd = node.end;
        } else {
            bodyStart = node.start;
            bodyEnd = node.end;
        }
    }
    @Override
    public int compareTo(Object o) {
        return 0;
    }
}
